`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date: 2023/12/06 10:55:14
// Design Name: 
// Module Name: divider
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 除法计算单元
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////


module divider #(
    parameter N = 5,
    parameter M = 3
) (
    input              clk,
    input              rstn,
    input      [N-1:0] dividend,  //被除数
    input      [M-1:0] divisor,   //除数
    input              data_rdy,  //数据使能
    output reg         res_rdy,   //是否计算完成
    output reg [N-1:0] merchant,  //商位宽：N
    output reg [N-1:0] remainder
);

  reg  [N-1:0] merchant_tmp;  // 临时计算的商数
  reg  [N-1:0] remainder_tmp;  // 临时计算的余数
  reg  [ 31:0] current_index;  // 计算次数，一个时钟周期内仅作一次计算

  wire [ 31:0] left_index;
  assign left_index = (N - M) >= 0 ? (N - M - current_index) : 0;  // 剩余的计算位数 

  // 时序电路改变计算索引
  always @(posedge clk or negedge rstn) begin
    if (!rstn) begin
      current_index <= 0;
    end else if (current_index < (N - M)) begin
      current_index <= current_index + 1;
    end
  end
  //组合电路生成数据
  always @(*) begin
    if (!rstn) begin
      merchant_tmp  = 0;
      remainder_tmp = 0;
    end else if (current_index == 0 && !res_rdy) begin
      if ((dividend >> left_index) >= divisor) begin
        // 商部计算
        merchant_tmp = 1'b1 << left_index;  // 首位做1，余位做0
        // 余部计算 减掉除数后补位
        remainder_tmp = left_index > 0 ? (dividend>>(left_index-1)) - (divisor << 1) :  dividend - divisor;
      end else begin
        merchant_tmp  = 0;  // 首部做0
        // 余部计算 减掉除数后补位
        remainder_tmp = left_index > 0 ? dividend >> (left_index - 1) : dividend;
      end
    end else if (current_index <= (N - M) && !res_rdy) begin
      if (remainder_tmp >= divisor) begin
        // 商部计算
        merchant_tmp = merchant + 1'b1 << left_index;  // 首位做1，余位做0
        // 余部计算 减掉除数后补位
        remainder_tmp = left_index > 0 ? {remainder, dividend[left_index-1]} - divisor << 1 :  remainder - divisor;
      end else begin
        // 余部计算 减掉除数后补位
        remainder_tmp = left_index > 0 ? {remainder, dividend[left_index-1]} : remainder;
      end
    end else begin
      merchant_tmp  = merchant;
      remainder_tmp = remainder;
    end
    // $display("left_index:%d,current_index:%d, remainder_tmp:%d, merchant_tmp:%d", left_index,
    //          current_index, remainder_tmp, merchant_tmp);

  end

  // 时序电路输出结果
  always @(posedge clk or negedge rstn) begin
    if (!rstn) begin
      res_rdy   <= 0;
      merchant  <= 0;
      remainder <= 0;
    end else if (current_index >= (N - M)) begin
      res_rdy   <= 1;
      merchant  <= merchant_tmp;
      remainder <= remainder_tmp;
    end else begin
      res_rdy   <= 0;
      merchant  <= merchant_tmp;
      remainder <= remainder_tmp;
    end
  end


endmodule
